import { Player } from "./Biz/Player";
import { PlayerManager } from "./Biz/PlayerMananger";
import { Room } from "./Biz/Room";
import { RoomManager } from "./Biz/RoomManager";
import { ApiMsgEnum, IApiPlayerJoinReq } from "./Common";
import { Connection, MyServer } from "./Core";
import { symlinkCommon } from "./Utils";
import { WebSocketServer } from "ws";

declare module "./Core" {
  interface Connection {
    playerId: number;
  }
}

symlinkCommon();

const server = new MyServer({
  port: 9876,
});

server.setApi(
  ApiMsgEnum.ApiPlayerJoin,
  (connection: Connection, data: IApiPlayerJoinReq) => {
    const { nickname } = data;
    const player = PlayerManager.Instance.createPlayer({
      nickname,
      connection,
    });

    const playerView = PlayerManager.Instance.getPlayerView(player);
    connection.playerId = player.id;

    PlayerManager.Instance.syncPlayers();

    return {
      player: playerView,
    };
    //return data + " server got";
  }
);

server.setApi(ApiMsgEnum.ApiPlayerList, (connection: Connection, data) => {
  return {
    list: PlayerManager.Instance.getPlayersView(),
  };
});

server.setApi(ApiMsgEnum.ApiRoomList, (connection: Connection, data) => {
  return {
    list: RoomManager.Instance.getRoomsView(),
  };
});

server.setApi(ApiMsgEnum.ApiRoomCreate, (connection: Connection, data) => {
  if (connection.playerId) {
    let newRoom = RoomManager.Instance.createRoom();

    let room = RoomManager.Instance.joinRoom(newRoom.id, connection.playerId);
    if (room) {
      RoomManager.Instance.syncRooms();
      return {
        room: RoomManager.Instance.getRoomView(room),
      };
    } else {
      throw new Error("no room found");
    }
  } else {
    throw new Error("Not logined");
  }
});

server.setApi(ApiMsgEnum.ApiRoomJoin, (connection: Connection, data) => {
  if (connection.playerId) {
    let room = RoomManager.Instance.joinRoom(data.rid, connection.playerId);
    if (room) {
      RoomManager.Instance.syncRooms();
      RoomManager.Instance.syncRoom(room.id);

      return {
        room: RoomManager.Instance.getRoomView(room),
      };
    } else {
      throw new Error("no room found");
    }
  } else {
    throw new Error("Not logined");
  }
});

server.setApi(ApiMsgEnum.ApiRoomLeave, (connection: Connection, data) => {
  if (connection.playerId) {
    const player = PlayerManager.Instance.idMapPlayer.get(connection.playerId);
    if (player) {
      const rid = player.rid;
      if (rid) {
        RoomManager.Instance.leaveRoom(rid, connection.playerId);
        PlayerManager.Instance.syncPlayers();
        RoomManager.Instance.syncRooms();
        RoomManager.Instance.syncRoom(rid);
        return {};
      } else {
        throw new Error("Player not in room");
      }
    } else {
      throw new Error("No player");
    }
  } else {
    throw new Error("Not logined");
  }
});

server.setApi(ApiMsgEnum.ApiGameStart, (connection: Connection, data) => {
  if (connection.playerId) {
    const player = PlayerManager.Instance.idMapPlayer.get(connection.playerId);
    if (player) {
      const rid = player.rid;
      if (rid) {
        RoomManager.Instance.startRoom(rid);
        PlayerManager.Instance.syncPlayers();
        RoomManager.Instance.syncRooms();
        RoomManager.Instance.syncRoom(rid);
        return {};
      } else {
        throw new Error("Player not in room");
      }
    } else {
      throw new Error("No player");
    }
  } else {
    throw new Error("Not logined");
  }
});

server.on("connection", (connection: Connection) => {
  console.log("client in", server.connections.size);
});

server.on("disconnection", (connection: Connection) => {
  console.log("client out", server.connections.size);

  if (connection.playerId) {
    PlayerManager.Instance.removePlayer(connection.playerId);
    PlayerManager.Instance.syncPlayers();
  }
});

server
  .start()
  .then(() => {
    console.log("server started");
  })
  .catch((e) => {
    console.log("server error", e);
  });

// const wss = new WebSocketServer({
//   port: 9876,
// });

// let inputs = [];

// wss.on("connection", (socket) => {
//   socket.on("message", (buffer) => {
//     try {
//       const str = buffer.toString();
//       const msg = JSON.parse(str);

//       const { name, data } = msg;
//       const { frameId, input } = data;

//       inputs.push(input);
//     } catch (err) {
//       console.log(err);
//     }

//     console.log(buffer.toString());
//   });

//   setInterval(() => {
//     const temp = inputs;
//     inputs = [];

//     const msg = {
//       name: ApiMsgEnum.MsgServerSync,
//       data: {
//         inputs: temp,
//       },
//     };

//     socket.send(JSON.stringify(msg));
//   }, 100);
// });

// wss.on("listening", () => {
//   console.log("listening!!!");
// });
